﻿using System;
using System.Collections.Generic;

namespace Test30.Core
{
    public class Circle : IEnumerable<Vec>
    {
        public Vec Center => _center;
        public int Radius => _radius;

        public Circle(Vec center, int radius)
        {
            if (radius < 0) throw new ArgumentOutOfRangeException($"radius", "The radius cannot be negative.");

            _center = center;
            _radius = radius;
        }

        public Circle(int radius)
            : this(Vec.Zero, radius)
        {
        }

        public bool IsEdge(Vec pos)
        {
            bool leadingEdge = true;
            if (_radius > 0)
            {
                leadingEdge = (pos - _center).LengthSquared > GetRadiusSquared(_radius - 1);
            }

            return leadingEdge;
        }

        #region IEnumerable<Vec> Members

        public IEnumerator<Vec> GetEnumerator()
        {
            Rect bounds = new Rect(Vec.Zero - _radius, Vec.One * (_radius + _radius + 1));

            foreach (Vec pos in bounds)
            {
                if (pos.LengthSquared <= GetRadiusSquared(_radius))
                {
                    yield return pos + _center;
                }
            }
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        private int GetRadiusSquared(int radius)
        {
            // if small enough, use the tuned radius to look best
            if (radius < RadiiSquared.Length) return RadiiSquared[radius];

            // otherwise just use a default
            return radius * radius;
        }

        private static readonly int[] RadiiSquared = new int[] { 0, 2, 5, 10, 18, 26, 38 };

        private readonly Vec _center;
        private readonly int _radius;
    }
}
